#include "Poller.hpp"
#include <cstring>

Poller::Poller() {
    epollFd_ = epoll_create1(EPOLL_CLOEXEC);
    if (epollFd_ == -1) {
        LOG << "Failed to create epoll file descriptor";
    }
    events_.resize(MAX_EVENT_NUM); // 初始大小，可以根据需要调整
}

Poller::~Poller() {
    close(epollFd_);
    mpFd2Channel_.clear();
}

/**
 * 将新的 Channel 添加到 epoll 实例中
 * @param request 需要添加的 Channel
 */
void Poller::epoll_add(const ChannelPtr& request) {
    // std::cout << "Poller::epoll_add" << std::endl;
    int fd = request->getFd();
    auto it=mpFd2Channel_.find(fd);
    if (it != mpFd2Channel_.end()) {
        LOG << "Duplicate channel for fd:" << fd;
        // return;
    }

    struct epoll_event event;
    memset(&event, 0, sizeof(event)); // 新增初始化
    event.data.fd = fd;
    event.events = request->getEvents();
    if (epoll_ctl(epollFd_, EPOLL_CTL_ADD, fd, &event) < 0) {
        // 错误处理示例：关闭异常文件描述符
        close(fd);
        LOG << "epoll_add failed, fd:" << fd;
        throw std::runtime_error("epoll_add error");
        return;
    }
    mpFd2Channel_[fd] = request;
}

/**
 * 修改已存在的 Channel
 * @param request 需要修改的 Channel
 */
void Poller::epoll_mod(const ChannelPtr& request) {
    int fd = request->getFd();
    struct epoll_event event;
    memset(&event, 0, sizeof(event)); // 新增初始化
    event.data.fd = fd;
    event.events = request->getEvents();
    if (epoll_ctl(epollFd_, EPOLL_CTL_MOD, fd, &event) < 0) {
        LOG << "Failed to modify file descriptor in epoll";
    }
    mpFd2Channel_[fd] = request;
}

/**
 * 从 epoll 实例中删除 Channel
 * @param request 需要删除的 Channel
 */
void Poller::epoll_del(const ChannelPtr& request) {
    int fd = request->getFd();
    if(!mpFd2Channel_.count(fd)) {
        LOG << "Channel not found: "<< fd;
        return;
    }
    if (epoll_ctl(epollFd_, EPOLL_CTL_DEL, fd, nullptr) < 0) {
        LOG << "Failed to delete file descriptor from epoll: "<< fd;
    }
    mpFd2Channel_.erase(fd);
}

/**
 * 通过 epoll_wait 获取就绪事件，并将就绪的 Channel 添加到 req 向量中
 * @param req 存储就绪的 Channel 的向量
 */
void Poller::poll(std::vector<ChannelPtr>& req) {
    int event_count = epoll_wait(epollFd_, &*events_.begin(), events_.size(), EPOLLWAIT_TIME);
    // std::cout << "Poller::poll" << std::endl;
    if (event_count < 0) {
        if(errno == EINTR) {
            LOG << "epoll_wait interrupted";
            return;
        }else{
            LOG << "epoll_wait error";
            return;
        }
    }
    // std::cout << "Poller::poll for" << std::endl;
    for (int i = 0; i < event_count; ++i) {
        int fd = events_[i].data.fd;
        ChannelPtr temp = mpFd2Channel_[fd];
        temp->setRetEvents(events_[i].events);
        req.emplace_back(std::move(temp));
    }
    // LOG << "Poller finished";
}